import models
import asyncio, random, string, time, datetime
import mySecurity, utility_classes
import yydrm, yygive


async def login(user_id, passwd):
    us = await models.user.findAll(where = 'user_id = ? AND password = ?', args = [user_id, passwd])
    if us:
        u = us[0]
        if u.status >= -1:
            token = get_token(u)
            online.add_item(u, token[0], token[1])
            data = {'data': {'user':{'nickname':u.nickname, 'status':u.status}}, 'token':token}
            return utility_classes.ReturnTemplate(0, data = data)
        else:
            return utility_classes.ReturnTemplate(2, '积分不足。')
    return utility_classes.ReturnTemplate(1, '用户名或密码错误。')
        

async def resetpasswd(user_id, newpasswd):
    u = await models.user.find(user_id)
    if u:
        u.password = newpasswd
        await u.update()
        return utility_classes.ReturnTemplate(0)
    return utility_classes.ReturnTemplate(1,'用户不存在。')


async def register(user_id, passwd, nickname):
    u = await models.user.find(user_id)
    if not u:
        u = models.user(user_id = user_id, password = passwd, nickname = nickname)
        await u.save()
        return True
    return False


async def top_up(user_id, card_key, friend_id = ''):
    if user_id == friend_id:
        return utility_classes.ReturnTemplate(3, '好友不存在。。')
    if friend_id:
        f = await models.user.find(friend_id)
        if not f:
            return utility_classes.ReturnTemplate(3, '好友不存在。。')
    
    u = await models.user.find(user_id)
    if u:
        r = await mySecurity.check_card_key(card_key)
        if r:
            u.balance += r
            oi = models.order_item(prepaid_for = user_id, payor = user_id, card_key = card_key, amount = r, friend_id = friend_id)
            await oi.save()
            
            #查看是否有赠送
            g = None
            for p in yygive.present_list:
                if r >= p.base_line:
                    g = p.give_amount
                    break
            if friend_id and g:
                u.balance += g
                oi = models.order_item(prepaid_for = user_id, friend_id = friend_id, amount = g)
                await oi.save()
                f.balance += g
                if f.status == -1 and f.balance >= yygive.points_per_day:
                    f.balance -= yygive.points_per_day
                    f.status = 0
                await f.update()
                oi = models.order_item(prepaid_for = friend_id, friend_id = user_id, amount = g)
                await oi.save()
            
            if u.status == -1 and u.balance >= yygive.points_per_day:
                u.balance -= yygive.points_per_day
                u.status = 0
            await u.update()
            if not online.exist_user(user_id):
                token = get_token(u)
                online.add_item(u, token[0], token[1])
                data = {'data':{'user':{'nickname':u.nickname, 'status':u.status}}, 'token':token}
                return utility_classes.ReturnTemplate(0, data = data)
            else:
                return utility_classes.ReturnTemplate(0)
        else:
            return utility_classes.ReturnTemplate(1, '卡密无效。。')
    return utility_classes.ReturnTemplate(2, '用户不存在。')


async def get_user_point(token):
    uid = online.get_user_id(token)
    u = await models.user.find(uid)
    res = {}
    res['balance'] = u.balance
    res['point_per_day'] = yygive.points_per_day
    l = await models.order_item.findAll('prepaid_for = ? and payor = ?', [uid, 'admin'])
    gtotal = 0
    for i in l:
        gtotal += i.amount
    res['gtotal'] = gtotal
    res['gtimes'] = len(l)
    return res


async def settlement():
    # 下午六点注销所有用户，扣除第二天费用，如果不够扣除，不执行扣除操作，直接把账户状态设置为不可用
    while(True):
        await asyncio.sleep(300)
        #h = datetime.datetime.now().hour
        #if h == 18:
        online.clear()
        us = await models.user.findAll('status != ? and status != ?', [-1, yydrm.root_status])
        print('需要清理', len(us))
        for u in us:
            print('开始清理')
            print(u.balance)
            if u.balance < yygive.points_per_day:
                print('设为不可用')
                u.status = -1
                print('设置成功')
            else:
                print('扣除积分')
                u.balance -= yygive.points_per_day
                print('扣除成功')
            print('保存用户')
            await u.update()
            print('用户保存成功')
        print('结算成功')




def check_user(token, api_name):
    #return True
    pro = online.get_proof(token[0])
    if pro != -1 and pro == token[1]:
        if online.get_user(token[0]).status >= yydrm.get_drm_status(api_name):
            return 0
        return 1001  #权限不够
    return 1000  #token验证失败。客户端重新登录

def get_token(user):
    token = ('').join(random.sample(string.ascii_letters + string.digits + '-_#+=', 18))
    proof = str(time.time())[-5:]
    return [token, proof]

def update_proof(token):
    return online.update_proof(token[0])


class online_user(object):
    __user_dic = {}  #key为user_id, value包含'user'，一个user对象，'token'，对应生成的token
    __token_dic = {}  #key为token，value为对应的proof

    def add_item(self, user, token, proof):
        x = self.__user_dic.get(user.user_id)
        if x:
            tmp = x['token']
            x['token'] = token
            x['user'] = user
            del self.__token_dic[tmp]
        else:
            self.__user_dic[user.user_id] = {'token':token, 'user':user}
        self.__token_dic[token] = {'user_id':user.user_id, 'proof':proof}

    def remove_user(self, token_or_user_id):
        if token_or_user_id in self.__token_dic:
            r = self.__token_dic.pop(token_or_user_id)
            del self.__user_dic[r['user_id']]
            return
        if token_or_user_id in self.remove_user:
            r = self.__user_dic.pop(token_or_user_id)
            del self.__token_dic[r['token']]
            return

    def get_proof(self, token):
        if token in self.__token_dic:
            return self.__token_dic[token]['proof']
        return -1

    def get_user(self, token):
        user_id = self.__token_dic[token]['user_id']
        return self.__user_dic[user_id]["user"]
    
    def get_user_id(self, token):
        user_id = self.__token_dic[token]['user_id']
        return user_id

    def get_token(self, user_id):
        return self.__user_dic[user_id]['token']

    def exist_user(self, user_id):
        return user_id in self.__user_dic

    def update_proof(self, token):
        #new_proof = str(time.time())[-5:]
        new_proof = '11111'
        self.__token_dic[token]['proof'] = new_proof
        return [token, new_proof]

    def clear(self):
        self.__user_dic.clear()
        self.__token_dic.clear()

online = online_user()